package zroute

import (
	"bytes"
	"fmt"
	"gitee.com/zouyang8210/zjson"
	"gitee.com/zouyang8210/zlogs"
	"gitee.com/zouyang8210/zunique"
	"github.com/gin-gonic/gin"
	"io"
	"net/http"
	"net/url"
)

type Router struct {
	router   *gin.Engine
	cross    bool
	useDebug bool
}

const (
	Rid = "rid"
)

// HTTP提交方式
const (
	HPost    = "POST"    //
	HGet     = "GET"     //
	HOptions = "OPTIONS" //
	HPut     = "PUT"     //
	HDelete  = "DELETE"  //
	HPatch   = "PATCH"   //
)

func (o *Router) Lister(port int, debug bool, handler gin.HandlerFunc) {
	if o.router == nil {
		o.router = gin.Default()
	}
	go func() {
		_ = o.start(port)
	}()

	o.router.Use(o.gw) // 设置网关函数
	if handler != nil {
		o.router.Use(handler)
	}
	o.useDebug = debug
	return
}
func (o *Router) ListerNotLog(port int, debug bool, handler gin.HandlerFunc) {
	if o.router == nil {
		o.router = gin.New()
	}
	go func() {
		_ = o.start(port)
	}()

	o.router.Use(o.gw) // 设置网关函数
	if handler != nil {
		o.router.Use(handler)
	}
	o.useDebug = debug
	return
}

// SetCross 设置是否启用跨域配置
func (o *Router) SetCross(b bool) {
	o.cross = b
}

// 网关
func (o *Router) gw(c *gin.Context) {
	method := c.Request.Method
	// 跨域设置
	if o.cross && o.CrossOption(c, method) {
		c.AbortWithStatus(http.StatusNoContent)
		return
	}
	if o.useDebug {
		content := o.setLog(c, method)
		zlogs.Msg(content)
	}
	c.Next()
}

// CrossOption 是否跨域协商
func (o *Router) CrossOption(c *gin.Context, method string) (res bool) {
	res = false
	c.Header("Access-Control-Allow-Origin", "*")
	c.Header("Access-Control-Allow-Headers", "*")
	c.Header("Access-Control-Allow-Methods", "POST,GET, OPTIONS,PUT,PATCH,DELETE")
	c.Header("Access-Control-Expose-Headers", "*")
	c.Header("Access-Control-Allow-Credentials", "true")
	if method == HOptions {
		res = true
	}
	return
}

// 开始API服务
func (o *Router) start(port int) (e error) {
	if e = o.router.Run(fmt.Sprintf(":%d", port)); e != nil {
		return
	}
	return
}

// 提出API请求参数,设置请求唯一ID
func (o *Router) setLog(c *gin.Context, method string) (content string) {
	switch method {
	case HPost, HPut, HPatch:
		buf, _ := c.GetRawData()
		c.Request.Body = io.NopCloser(bytes.NewBuffer(buf))
		content, _ = url.QueryUnescape(string(buf))
	case HGet, HDelete:
		content = c.Request.URL.RawQuery
	}
	rid := zunique.GetStrTwitterId() //为此次访问加上一个唯一IDs
	c.Header(Rid, rid)
	return
}

func (o *Router) AddRoutePost(relativePath string, handlers ...gin.HandlerFunc) {
	o.router.POST(relativePath, handlers...)
}

func (o *Router) AddRouteGet(relativePath string, handlers ...gin.HandlerFunc) {
	o.router.GET(relativePath, handlers...)
}

func (o *Router) AddRoutePut(relativePath string, handlers ...gin.HandlerFunc) {
	o.router.PUT(relativePath, handlers...)
}

func (o *Router) AddRouteDelete(relativePath string, handlers ...gin.HandlerFunc) {
	o.router.DELETE(relativePath, handlers...)
}

func (o *Router) AddRoutePATCH(relativePath string, handlers ...gin.HandlerFunc) {
	o.router.PATCH(relativePath, handlers...)
}

func (o *Router) AddRoutStaticFs(relativePath, path string) {
	o.router.StaticFS(relativePath, http.Dir(path))
}

func (o *Router) ResponseObj(c *gin.Context, res interface{}) {
	c.JSON(http.StatusOK, res)
	if o.useDebug {
		fmt.Printf("Return:%+v\n", res)
	}
	return
}

func (o *Router) Response(c *gin.Context, httpStatus int, res interface{}) {
	c.JSON(httpStatus, res)
	return
}

func (o *Router) ParameterToMap(params string) (paramList map[string]interface{}, e error) {
	if e = zjson.ToObj(params, &paramList); e != nil {
		return
	}
	return
}
